//Inverted Page Table
#ifndef IPT_H
#define IPT_H

#include "../machine/machine.h"
#include "../threads/list.h"
#include "addrspace.h"
#include "../threads/synch.h"

using namespace std;

class IPTentry
{
private:
	int physicalPage;
	int virtualPage;
	//int dataType; //(0=code; 1=data; 2=mixed; 3=stack; 4=?)
	bool dirty;
	bool valid;
	bool readOnly;
	bool use;
	int processId;
public:
	IPTentry();
	~IPTentry();
	void MakeClean() { dirty = false; }
	void MakeDirty() { dirty = true; }
	void MakeValid() { valid = true; }
	void Reset();
	bool isDirty() { return dirty; }
	int GetVirtual() { return virtualPage; }
	int GetId() { return processId; }
	void SetPhysical (int physical) { physicalPage=physical; }
	void SetVirtual (int incomingVirtual) { virtualPage=incomingVirtual; }
	void SetProcessId (int id) { processId = id; }
	void PopulateTLB();
};		
	

class IPT
{
private:
	IPTentry* iptTable; //array of entries; size = to number of physical pages
	List fifoList;	//list of memory indexes as they are added; when FIFO eviction is specified, the last index in the list
					//is selected for eviction and that index is then added to the beginning of the list
	int currentListSize;
	Lock* iptLock;
public:
	IPT();
	~IPT();

	void Assign(int physical, int incomingVirtual, int processId);
	void PageModified (unsigned int index) { iptTable[index].MakeDirty(); } //makes page dirty
	bool isDirty(int index) { return iptTable[index].isDirty(); }
	void Update(int physical, int incomingVirtual, int processId);
	int GetVirtual(int physical) { return iptTable[physical].GetVirtual(); }
	int FIFO();
	int GetId(int physical) { return iptTable[physical].GetId(); }
	void MakeDirty(int physical) { iptTable[physical].MakeDirty(); }
	void PopulateTLBSearch(int vpn, int id);
	void PopulateTLB(int ppn) { iptTable[ppn].PopulateTLB(); }
	void DeallocateSpace(AddrSpace*);
	void DeallocateThread(AddrSpace*, int);

};
#endif
